package com.tea.zxql.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tea.zxql.constants.KeysConstants;
import com.tea.zxql.constants.SimConstants;
import com.tea.zxql.domain.Sim;
import com.tea.zxql.domain.dto.PageDTO;
import com.tea.zxql.domain.dto.SimDTO;
import com.tea.zxql.domain.query.SimQuery;
import com.tea.zxql.domain.vo.SimVO;
import com.tea.zxql.mapper.UserMapper;
import com.tea.zxql.service.SimService;
import com.tea.zxql.mapper.SimMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * @author sdcfj
 * @description 针对表【sim】的数据库操作Service实现
 * @createDate 2025-07-28 14:58:18
 */
@Service
public class SimServiceImpl extends ServiceImpl<SimMapper, Sim>
    implements SimService{

    @Autowired
    private SimMapper simMapper;

    @Autowired
    private UserMapper userMapper;


    @Autowired
    private StringRedisTemplate redisTemplate;


    /**
     * 分页查询SIM卡信息
     *
     * @param query 查询条件封装对象，包含分页信息和公司筛选条件
     * @return 分页结果对象，包含SIM卡数据列表、总页数和总记录数
     */
    @Override
    public PageDTO<SimDTO> getPage(SimQuery query) {

        // 准备分页对象
        Page<Sim> page = new Page<>(query.getPageNo(), query.getPageSize());
        // 初始化公司变量
        String company = query.getCompany();
        // 初始化DTO
        PageDTO<SimDTO> pageDTO =  new PageDTO<>();
        // 两种情况
        if (StpUtil.hasRole("SuperAdmin")) {
            // 1.超级管理员
            // 超管可以查询所有的设备，也可以查询指定公司的设备
            Page<Sim> simPage = simMapper.selectMyPage(page, company);

            pageDTO.setPages((int) simPage.getPages());
            pageDTO.setTotal((int) simPage.getTotal());

            List<Sim> sims = simPage.getRecords();
            if (sims == null) {
                pageDTO.setList(Collections.emptyList());
            } else {
                List<SimDTO> list = BeanUtil.copyToList(sims, SimDTO.class);
                pageDTO.setList(list);
            }
            return pageDTO;
        } else {
            // 2.普通管理员
            // 普通管理员只能查询本公司的设备
            company = userMapper.getCompanyByUserId(StpUtil.getLoginIdAsInt());


            Page<Sim> simPage = simMapper.selectMyPage(page, company);


            pageDTO.setPages((int) simPage.getPages());
            pageDTO.setTotal((int) simPage.getTotal());
            List<Sim> sims = simPage.getRecords();
            if (sims == null) {
                pageDTO.setList(Collections.emptyList());
            } else {
                List<SimDTO> list = BeanUtil.copyToList(sims, SimDTO.class);
                pageDTO.setList(list);
            }

            return pageDTO;
        }
    }

    /**
     * 根据ID更新SIM卡信息
     *
     * @param sim 包含更新信息的SIM卡数据传输对象
     */
    @Override
    @Transactional
    public void updateSimById(SimDTO sim) {

        if (!KeysConstants.SIM_KEY.equals(sim.getSimKey())) {
            throw new RuntimeException("非法操作");
        }


        if (sim.getBuzzer() == null || "".equals(sim.getBuzzer())) {
            sim.setBuzzer("0");
            if (redisTemplate.opsForValue().get(sim.getSimId() + ".old.buzzer") != null ) {
                sim.setBuzzer(redisTemplate.opsForValue().get(sim.getSimId() + ".old.buzzer"));
            }
        }

        if (sim.getLed() == null || "".equals(sim.getLed())) {
            sim.setLed("0");
            if (redisTemplate.opsForValue().get(sim.getSimId() + ".old.led") != null) {
                sim.setLed(redisTemplate.opsForValue().get(sim.getSimId() + ".old.led"));
            }
        }

        // 把蜂鸣器和led状态写入redis
        redisTemplate.opsForValue().set(sim.getSimId() + ".old.buzzer", sim.getBuzzer());
        redisTemplate.opsForValue().set(sim.getSimId() + ".old.led", sim.getLed());



        redisTemplate.opsForValue().set("sim.online:" + sim.getSimId(), "1", 30, TimeUnit.SECONDS);

        LambdaQueryWrapper<Sim> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Sim::getSimId, sim.getSimId());
        List<Sim> list = this.list(queryWrapper);
        if (list == null || list.size() == 0) {
            sim.setCreateTime(new Date());
            sim.setUpdateTime(new Date());
            Sim sim1 = BeanUtil.copyProperties(sim, Sim.class);
            // 手动设置状态
            if (sim1.getStatus() == null) {
                sim1.setStatus(0);
            }
            simMapper.insert(sim1);
            redisTemplate.opsForValue().set("simId" + sim1.getSimId() + ":", String.valueOf(sim1.getId()), 1, TimeUnit.DAYS);
            return;
        }


        // 通过redis获取

        if(redisTemplate.opsForValue().get(sim.getSimId() + "userId") == null) {
            throw new RuntimeException("请先登录！");
        }

        // 此处已经登录，手动设置状态为1
        sim.setStatus("1");



        // 获取sim的id

        String company = redisTemplate.opsForValue().get(sim.getSimId() + "company");
        if (redisTemplate.opsForValue().get("simId" + sim.getSimId() + ":") != null) {
            Long id = Long.valueOf(redisTemplate.opsForValue().get("simId" + sim.getSimId() + ":"));
            // 代表前面第一次插入了这个数据，需要的是更新操作
            Sim sim1 = this.getOne(new LambdaQueryWrapper<Sim>().eq(Sim::getId, id));

            sim1.setCompany(company);
            sim1.setUpdateTime(new Date());



            simMapper.update(sim1, new LambdaUpdateWrapper<Sim>().eq(Sim::getId, id));
            // 清除redis
            redisTemplate.delete("simId" + sim.getSimId() + ":");
            return;
        }


        sim.setCompany(company);


        sim.setUpdateTime(new Date());
        sim.setCreateTime(new Date());

        Sim sim1 = BeanUtil.copyProperties(sim, Sim.class);
        simMapper.insert(sim1);

        // 直接存到redis中，后面直接redis中读取
        redisTemplate.opsForValue().set(sim1.getSimId() + ".data", JSONUtil.toJsonStr(sim1), 1, TimeUnit.MINUTES);
        // 判断
    }

    /**
     * 获取SIM卡数据
     *
     * @return SIM卡数据的JSON字符串表示
     */
    @Override
    public String getSimData() {

        // 第一步：获取用户id
        Integer userId = StpUtil.getLoginIdAsInt();

        // 第二步：通过用户id获取到simId
        String simId = redisTemplate.opsForValue().get(userId + "userIdGetsimId:");


        Sim sim = simMapper.selectBySimId(simId);
        redisTemplate.opsForValue().set(sim.getSimId() + ".data", JSONUtil.toJsonStr(sim), 1, TimeUnit.MINUTES);


        // 第三步：获取simId对应的数据
        String simJSON = redisTemplate.opsForValue().get(simId + ".data");


        return simJSON;
    }

    /**
     * 更新设备状态（蜂鸣器或LED灯）
     *
     * @param sim 包含设备类型和状态信息的SIM卡数据传输对象
     */
    @Override
    public void updateDeviceStatus(SimDTO sim) {

        // 这个地方是前端发送的请求，要修改蜂鸣器或者是led灯的状态

        if (SimConstants.DEVICE_BUZZER.equals(sim.getDevice())) {
            redisTemplate.opsForValue().set(sim.getSimId() + ".buzzer", sim.getStatus(),10, TimeUnit.SECONDS);
        } else if (SimConstants.DEVICE_LED.equals(sim.getDevice())) {
            redisTemplate.opsForValue().set(sim.getSimId() + ".led", sim.getStatus(), 10, TimeUnit.SECONDS);
        }

    }

    /**
     * 获取设备状态信息
     *
     * @param simId SIM卡ID
     * @return 包含蜂鸣器和LED状态信息的视图对象
     */
    @Override
    public SimVO getStatus(String simId) {


        String buzzerStatus = redisTemplate.opsForValue().get(simId + ".old.buzzer");
        String ledStatus = redisTemplate.opsForValue().get(simId + ".old.led");

        if (redisTemplate.opsForValue().get(simId + ".buzzer") != null) {
            buzzerStatus = redisTemplate.opsForValue().get(simId + ".buzzer");
            redisTemplate.opsForValue().set(simId + ".old.buzzer", buzzerStatus);
        }
        if (redisTemplate.opsForValue().get(simId + ".led") != null) {
            ledStatus = redisTemplate.opsForValue().get(simId + ".led");
            redisTemplate.opsForValue().set(simId + ".old.led", ledStatus);
        }



        LambdaUpdateWrapper<Sim> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(Sim::getSimId, simId)
                .set(Sim::getBuzzer, buzzerStatus)
                .set(Sim::getLed, ledStatus);
                simMapper.update(null, updateWrapper);

                SimVO simVO = new SimVO();
                simVO.setBuzzer(buzzerStatus);
                simVO.setLed(ledStatus);

        // 清空redis中存储的状态
        redisTemplate.delete(simId + ".buzzer");
        redisTemplate.delete(simId + ".led");
        return simVO;
    }

    /**
     * 检查设备状态是否已删除
     *
     * @param device 设备类型
     */
    @Override
    public void isStatusDelete(String device) {

        Integer userId = StpUtil.getLoginIdAsInt();

        String simId = redisTemplate.opsForValue().get(userId + "userIdGetsimId:");

        if (redisTemplate.opsForValue().get(simId + "." + device) != null) {
            throw new RuntimeException("硬件还没有修改该元器件的状态！");
        }


    }

    /**
     * 设备更新状态
     *
     * @param sim 包含更新状态信息的SIM卡数据传输对象
     */
    @Override
    public void deviceUpdateSataus(SimDTO sim) {

        // 我们统一把状态统一保存在redis中


        // 第一步：获取用户simId
        String simId = sim.getSimId();

        if (sim.getBuzzer() != null) {
            redisTemplate.opsForValue().set(simId + ".old.buzzer", sim.getBuzzer());
        }
        if (sim.getLed() != null) {
            redisTemplate.opsForValue().set(simId + ".old.led", sim.getLed());
        }




    }

    /**
     * 获取LED和蜂鸣器状态
     *
     * @param simId SIM卡ID
     * @return 包含LED和蜂鸣器状态信息的视图对象
     */
    @Override
    public SimVO getLedAndBuzzerStatus(String simId) {

        SimVO simVO = new SimVO();
        simVO.setLed(redisTemplate.opsForValue().get(simId + ".old.led"));
        simVO.setBuzzer(redisTemplate.opsForValue().get(simId + ".old.buzzer"));

        return simVO;
    }
}
